import qs from "./qs"
import { DynamicIndex } from "./types/commonTypes";
const token:string = ""
// 自定义通用请求头 Custom generic request headers
const commonHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Content-Type": "application/json;charset=UTF-8",
  "X-Requested-With": "XMLHttpRequest",
  token
}
const urlencodedReg = new RegExp("application/x-www-form-urlencoded+");
const jsonReg = new RegExp("application/json+");
const BaseURL = ""
/**
 * vite 不支持process 判断是否为开发模式的时候用 import.meta.env.DEV
 * vite doesn't support process, use import.meta.env.DEV when judging whether it is in development mode
 */
const useUrl = process.env.NODE_ENV === "development" ? "/api" : `${BaseURL}api`
let reqNum = 0;
function setLoading() {
  if (!reqNum) {
    // 添加加载动画 Add loading animation
  }
  reqNum++;
}
function clearLoading() {
  reqNum--;
  if (reqNum > 0) return
  // 清除加载动画 Clear loading animation
}
const ErrorMessages: DynamicIndex = {}
const controller = new AbortController();
const signal = controller.signal;
interface RequestProps extends DynamicIndex {
  method?: "POST" | "GET" | "PUT" | "DELETE" | 'etc',
  timeout?: number
  headers?: DynamicIndex
  showToast?: boolean,
  params?: DynamicIndex,
  data?: DynamicIndex
}
function request(url: string, option: RequestProps) {
  return new Promise(async (resolve, reject) => {
    let showToast: boolean | undefined = true;
    if ("showToast" in option) {
      showToast = option.showToast;
    }
    if (showToast) {
      setLoading();
    }
    const headers = { ...commonHeaders, ...(option.headers || {}) };
    const timeout = option.timeout || 60000;
    const method = !!option.method ? option.method.toUpperCase() : "GET";
    const params = qs.stringify(option.params || {});
    let data: DynamicIndex | string | null = option.data || {};
    url += !!params ? `?${params}` : ""
    if (urlencodedReg.test(headers["Content-Type"])) {
      data = qs.stringify(data);
    }
    if (jsonReg.test(headers["Content-Type"])) {
      data = JSON.stringify(data);
    }
    if (method === "GET") {
      data = null
    }
    try {
      const res: any = await Promise.race([
        fetch(useUrl + url, {
          method,
          headers,
          body: data as BodyInit,
          mode: "cors",
          signal
        }),
        timeoutPromise(timeout)
      ])
      if (showToast) {
        clearLoading();
      }
      if (res.status === 200) {
        const { code, msg, data } = await res.json();
        if (Number(code) === 1) {
          return resolve({ code, msg, data })
        }
        return reject({ code, msg, data })
      }
      const errMsg = ErrorMessages[res.status]
      if (showToast) {
        // 提示错误 Error message
        if (!!errMsg) {
          alert(errMsg)
        } else {
          alert(ErrorMessages['UNKNOWN_ERROR'])
        }
      }
      reject(res.statusText);
    } catch (error) {
      if (showToast) {
        clearLoading();
      }
      console.error("数据请求错误-:", error)
    }
  })
}

export const $get = (url: string, data: DynamicIndex, option: RequestProps) => request(url, { params: data, ...option })

export const $post = (url: string, data: DynamicIndex, option: RequestProps) => request(url, { data, method: "POST", ...option })

export function upload(data: DynamicIndex, option: RequestProps) {
  const url = option.url || "/users/upload";
  let params = new FormData();
  for (const key in data) {
    if (Object.prototype.hasOwnProperty.call(data, key)) {
      const value = data[key];
      params.append(key, value);
    }
  }
  return $post(url, data, {
    headers: { "Content-Type": "multipart/form-data;charset=UTF-8" },
    ...option
  })
}

function timeoutPromise(time: number) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      controller.abort();
      return resolve({ status: 504, statusText: "timeout" })
    }, time)
  })
}

// 错误处理
export function dealError(error: any) {
  if (typeof error === "string") {
    alert(error)
  } else if (!!error.msg) {
    alert(error.msg)
  } else {
    console.error("获取数据错误:", error)
  }
}